package com.cskaoyan.javase.oop3._2inner._1member._2basic;

/**
 * 在具体讲解访问特别之前,我们要先明确以下两个原则:
 *      1.(成员)内部类和包裹它的外围类之间是"好兄弟"的关系,互相访问不受权限限制,即便是私有也可以任意互相访问.
 *      2.成员内部类对象依赖于外围类对象,这样的一句话,说明了什么?
 *      要想得到成员内部类对象,必须先创建外围类对象,而且成员内部类对象会持有外围类对象的引用作为自身成员变量
 *      现在思考以下访问:
 *          a.在成员内部类的成员方法,构造器,构造代码块中访问外围类成员,如何访问呢?
 *          --> 思考: 在以上成员内部类的结构中,存在几个对象?
 *          2个对象,外围类对象以及自身对象
 *          (语法重点):
 *          自身对象仍然用this关键字指向它
 *          外围类对象用"外围类类名.this"指向它
 *          明确以上问题后,如何访问外围类成员呢?
 *          直接访问,不受权限限制,但是要注意同名的问题,同名时用"外围类类名.this"指向外围类对象,以区分.
 *
 *          b.在外围类的方法中,有没有成员内部类对象? 没有,要想访问成员内部类成员,必须创建成员内部类对象
 *          c.外围类的静态方法和成员方法还是有不同的,不同点在于有没有this
 *              成员方法中存在this有自身外围类对象,但静态方法中没有this没有自身外围类对象
 *              这样的区别,就导致了它们访问成员内部类成员时就有了差异.
 *
 *          e.(重点)如何在外围类中创建成员内部类对象?
 *              1.外围类的成员方法,已经存在外围类对象了,可以直接创建成员内部类对象
 *              2.外围类的静态方法,没有外围类对象,需要先创建外围类对象,然后在外围类对象基础上创建成员内部类对象
 *
 * (重点)成员内部类的使用,各种访问的特点:
 *      1.(重点)成员内部类内部访问外围类成员
 *          访问的位置只有:成员方法,构造器,构造代码块
 *          没有静态方法
 *          访问的特点: 直接访问,如有同名用,用
 *          "外围类类名.this"指向外围类对象区分
 *
 *      2.(重点)外围类访问成员内部类成员成员
 *          访问位置: 成员方法和静态方法
 *          访问特点: 需要创建成员内部类对象
 *              成员方法中可以直接创建
 *              静态方法中需要先创建外围类对象,然后再创建成员内部类对象
 *
 *      一般来说,既然使用内部类了,就是为了隐藏类,保护类,所以内部类一般访问权限都是private,所以以下访问不作为重点,仅供了解
 *      3.外部类访问成员内部类成员
 *          首先这个访问的过程,全程都受访问权限限制
 *          首先需要外围类的权限,其次需要成员内部类的权限,最后还需要成员内部类成员的权限,这些权限缺一不可,缺少一个都不能访问
 *          在有权限的前提下,如何访问呢?
 *          创建成员内部类对象,然后访问
 *          -->
 *          需要先创建外围类对象
 *
 *      4.成员内部类访问外部类成员
 *          可以访问,创建对象即可
 *          也是全程受权限限制
 *
 * @since 10:14
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        EnclosedClazz ec = new EnclosedClazz();
        EnclosedClazz.InnerClazz ic = ec.new InnerClazz();

        // 在外部类当中,用"外围类类名.成员内部类类名"表示一个内部类的引用的数据类型
        EnclosedClazz.InnerClazz ic2 = new EnclosedClazz().new InnerClazz();
        System.out.println(ic2.b);
        // System.out.println(ic2.a);
    }
}

// 外围类
class EnclosedClazz {
    private int a;
    private int num = 200;
    int b = 100;
    static final int NUM = 100;

    // 外围类的成员方法
    public void testEnclosed() {
        System.out.println(this);
        InnerClazz ic = new InnerClazz();
        System.out.println(ic.a);
        System.out.println(ic.b);
        // 以上创建对象, 仍然是基于外围类对象的,补全代码如下
        InnerClazz ic2 = this.new InnerClazz();
    }

    // 外围类的静态成员方法
    public static void testStatic() {
        EnclosedClazz ec = new EnclosedClazz();
        InnerClazz ic = ec.new InnerClazz();
        // 以上代码二合一,链式调用
        InnerClazz ic2 = new EnclosedClazz().new InnerClazz();
    }

    // 成员内部类
    class InnerClazz extends Object {
        private int a;
        int b = 10;
        static final int NUM = 10;
        static final String VAR = "hello";

        // 成员内部类的成员方法中访问外围类成员
        public void testInner() {
            System.out.println(num);
            System.out.println(a);
            System.out.println(b);
            System.out.println(EnclosedClazz.this.a);
            System.out.println(EnclosedClazz.this.b);
            System.out.println(EnclosedClazz.NUM);
            System.out.println(InnerClazz.NUM);

            // A a = new A();
        }

        public void test(int a){
            System.out.println(a);
            System.out.println(this.a);
            System.out.println(EnclosedClazz.this.a);
        }
    }
}
class A{}